﻿
Imports System.Windows.Input
Imports System.Windows.Threading
Imports System.Runtime.Serialization
Imports System.Security.Permissions



Namespace Command

    <CLSCompliant(True), Serializable()>
    Public Class RelayCommand
        Implements ICommand, ISerializable
#Region "Fields"

        ''' <summary>
        ''' The m_ execute
        ''' </summary>
        <NonSerialized> _
        ReadOnly m_Execute As Action(Of Object)
        ''' <summary>
        ''' The m_ can execute
        ''' </summary>
        <NonSerialized> _
        ReadOnly m_CanExecute As Predicate(Of Object)

#End Region

#Region "Constructors"

        ''' <summary>
        ''' Creates a new command that can always execute.
        ''' </summary>
        ''' <param name="execute">The execution logic.</param>
        Public Sub New(execute As Action(Of Object))
            Me.New(execute, Nothing)
            CommandCanExecute = True
        End Sub

        ''' <summary>
        ''' Creates a new command.
        ''' </summary>
        ''' <param name="execute">The execution logic.</param>
        ''' <param name="canExecute">The execution status logic.</param>
        ''' <exception cref="System.ArgumentNullException">execute</exception>
        Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
            If execute Is Nothing Then
                Throw New ArgumentNullException("execute")
            End If

            m_Execute = execute
            m_CanExecute = canExecute
        End Sub
        ''' <summary>
        ''' Initializes a new instance of the <see cref="RelayCommand"/> class.
        ''' </summary>
        Protected Sub New()

        End Sub

#End Region

#Region "ICommand Members"

        ''' <summary>
        ''' Defines the method that determines whether the command can execute in its current state.
        ''' </summary>
        ''' <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
        ''' <returns>true if this command can be executed; otherwise, false.</returns>
        <DebuggerStepThrough()> _
        Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
            Return If(m_CanExecute Is Nothing, CommandCanExecute, m_CanExecute(parameter))
        End Function

        ''' <summary>
        ''' Occurs when [can execute changed].	
        ''' </summary>
        ''' <remarks></remarks>
        Public Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
        ''' <summary>
        ''' Called when [can execute changed].
        ''' </summary>
        Public Sub OnCanExecuteChanged()
            RaiseEvent CanExecuteChanged(Me, EventArgs.Empty)
        End Sub

        ''' <summary>
        ''' Defines the method to be called when the command is invoked.
        ''' </summary>
        ''' <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
        Public Sub Execute(parameter As Object) Implements ICommand.Execute
            m_Execute(parameter)
        End Sub

#End Region

        ''' <summary>
        ''' Gets or sets a value indicating whether [command can execute].
        ''' </summary>
        ''' <value><c>true</c> if [command can execute]; otherwise, <c>false</c>.</value>
        Public Property CommandCanExecute() As Boolean
            Get
                Return m_CommandCanExecute
            End Get
            Set(ByVal value As Boolean)
                If m_CommandCanExecute = value Then
                    Return
                End If
                m_CommandCanExecute = value
                RaiseEvent CanExecuteChanged(Me, EventArgs.Empty)
            End Set
        End Property
        ''' <summary>
        ''' The m_ command can execute
        ''' </summary>
        Private m_CommandCanExecute As Boolean



#Region "Deserialization Constructor"

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)

            m_CommandCanExecute = CType(info.GetValue("m_CommandCanExecute", GetType(Boolean)), Boolean)

        End Sub

#End Region

#Region "ISerializable Implementation"

        <SecurityPermission(SecurityAction.Demand, SerializationFormatter:=True)> _
        Public Overridable Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
                Implements ISerializable.GetObjectData

            info.AddValue("m_CommandCanExecute", m_CommandCanExecute)

        End Sub

#End Region
    End Class

End Namespace
